package ch.hslu.gl20vscpudemo;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

/**
 * Asynchronous Surface View Load Bitmaps asynchronous
 */
public class AsyncSurfaceView extends SurfaceView implements SurfaceHolder.Callback {

	// members ///////////////////////////////////////////////////////////////////
	private SurfaceHolder mHolder;
	private CanvasWorkerThread mCanvasWorkerThread;
	
	protected int nSizeWidth;
	protected int nSizeHeight;
	protected Bitmap mBitmap;

	// constructor ///////////////////////////////////////////////////////////////
	/**
	 * 
	 * @param context Activity context
	 * @param w default image weight, this value is overriding by onDraw method
	 * @param h default image hight
	 */
	public AsyncSurfaceView(Context context, int w, int h) {
		super(context);

		// Install a SurfaceHolder.Callback so we get notified when the
		// underlying surface is created and destroyed.
		mHolder = getHolder();
		mHolder.addCallback(this);
		mCanvasWorkerThread = new CanvasWorkerThread(getHolder(), this);
		mBitmap = null;//bmp;
		nSizeWidth = w; // load default size
		nSizeHeight = h; // override by onDraw method
 //   Log.d(this.toString(), "w, h" + Integer.toString(bmp.getWidth()) + ", " + Integer.toString(bmp.getHeight()));
	}

	// protected methods /////////////////////////////////////////////////////////
	/** SurfaceView */
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		nSizeWidth = canvas.getWidth();
		nSizeHeight = canvas.getHeight();
		canvas.drawColor(Color.BLACK);
		if (null != mBitmap) {
			canvas.drawBitmap(mBitmap, 0, 0, null);
		}
	}

	// public methods ////////////////////////////////////////////////////////////

	/** SurfaceHolder.Callback */
	public void surfaceCreated(SurfaceHolder holder) {
		mCanvasWorkerThread.runTurnOn();
		mCanvasWorkerThread.start();
	}

	/** SurfaceHolder.Callback */
	public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
		// If your preview can change or rotate, take care of those events here.
		// Make sure to stop the preview before resizing or reformatting it.

		if (mHolder.getSurface() == null) {
			// preview surface does not exist
			return;
		}
	}

	/** SurfaceHolder.Callback */
	public void surfaceDestroyed(SurfaceHolder holder) {
		boolean retry = true;
		// mCanvasWorkerThread.setRunning(false);
		while (retry) {
			mCanvasWorkerThread.runTurnOff();
			try {
				mCanvasWorkerThread.join();
				retry = false;
			} catch (InterruptedException e) {
				// Log.e(this.toString(), "Therad Join error");
			}
		}
	}
	
	public void pushImage(Bitmap bmp){
		mBitmap = bmp;
	}

	/**
	 * nested class: thread for canvas drawing
	 * 
	 * @see <a
	 *      href="http://http://www.droidnova.com/playing-with-graphics-in-android-part-ii,160.html/">
	 *      droidnova.com</a>
	 */
	private class CanvasWorkerThread extends Thread {

		// members /////////////////////////////////////////////////////////////////
		private SurfaceHolder mSurfaceHolder; // member surface holder
		private AsyncSurfaceView mPanel; // member panel
		private boolean bRun;

		// constructor /////////////////////////////////////////////////////////////
		public CanvasWorkerThread(SurfaceHolder surfaceHolder, AsyncSurfaceView panel) {
			mSurfaceHolder = surfaceHolder;
			mPanel = panel;
			bRun = false;
		}

		public void runTurnOn() {
			bRun = true;
		}

		public void runTurnOff() {
			bRun = false;
		}

		// public methods //////////////////////////////////////////////////////////
		@Override
		public void run() {
			Canvas mCanvas;
			while (bRun) {
				if((nSizeWidth != mBitmap.getWidth()) || (nSizeHeight != mBitmap.getHeight())){
					Bitmap bmp = Bitmap.createScaledBitmap(mBitmap, nSizeWidth, nSizeHeight, false);
					mBitmap = bmp;
				}
				
				// set Canvas object to null and open a try block
				mCanvas = null;
				// lock the canvas, draw on it, unlock and post it.
				mCanvas = mSurfaceHolder.lockCanvas();
				if (null != mCanvas) {
					synchronized (mSurfaceHolder) {
						// synchronize drawing with the SurfaceHolder
						mPanel.onDraw(mCanvas);
					}
					mSurfaceHolder.unlockCanvasAndPost(mCanvas);
					if(!mSurfaceHolder.isCreating()){
						bRun = false;
					}
					// mimimize the double buffered flickering problem
					try {
						Thread.sleep(100);
					} catch (InterruptedException e) {
						// Log.e(this.toString(), e.toString());
					}
				}
			}
		}
	}
}
